package pl.edu.pw.MidEmu.Logic;

import java.awt.Point;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.swing.JTextPane;
import javax.swing.JViewport;

/**
 * Service class responsible for handling process outputs
 * @author Mateusz Starodab
 *
 */
public class ProcessOutputHandler extends Thread
{
	/**
	 * Enumeration with output types
	 * @author Mateusz Starodab
	 *
	 */
	public enum OutputType
	{
		Error, Output
	}

	private String _identity;

	private InputStreamReader _inReader;

	private OutputType _outputType;

	private StringBuffer dataBuffer;

	private boolean isClosing = false;

	private JTextPane subscribed;

	/**
	 * Constructor
	 * @param stream Output stream to handle
	 */
	public ProcessOutputHandler(InputStream stream)
	{
		BufferedInputStream inStream = new BufferedInputStream(stream);
		_inReader = new InputStreamReader(inStream);

		dataBuffer = new StringBuffer(65536);
	}

	/**
	 * Gets output type
	 * @return
	 */
	public OutputType getOutputType()
	{
		return _outputType;
	}

	/**
	 * Marks output stream as closing
	 */
	public void markAsClosing()
	{
		isClosing = true;
	}

	@Override
	/**
	 * Run method supporting process output handler
	 */
	public void run()
	{
		try
		{
			char[] buffer = new char[2048];
			int a = 0;
			while ((a = _inReader.read(buffer, 0, buffer.length)) > 0)
			{
				String inString = new String(buffer, 0, a);
				System.out.print(_identity + " - " + _outputType.toString() + ": " + inString);
				dataBuffer.append(inString);

				if (subscribed != null)
				{
					subscribed.getDocument().insertString(subscribed.getDocument().getLength(), inString, null);
					((JViewport) subscribed.getParent()).setViewPosition(new Point(0, subscribed.getHeight()));
				}

			}
		}
		catch (Exception ex)
		{
			if (!isClosing)
			{
				System.err.println("Exception while handling output");
				ex.printStackTrace();
			}
		}
	}

	/**
	 * Gets output identity
	 * @return Identity
	 */
	public String getIdentity()
	{
		return _identity;
	}

	/**
	 * Sets output identity
	 * @param identity Identity to set
	 */
	public void setIdentity(String identity)
	{
		_identity = identity;
	}

	/**
	 * Sets output type
	 * @param outputType Output type to set
	 */
	public void setOutputType(OutputType outputType)
	{
		_outputType = outputType;
	}

	/**
	 * Subscribes for output changes
	 * @param pane Panel toi display output on
	 */
	public void subscribeForData(JTextPane pane)
	{
		subscribed = pane;
		if (dataBuffer.length() > 0)
		{
			pane.setText(dataBuffer.toString());
		}
	}

	/**
	 * Terminates output handler
	 */
	public void terminate()
	{
		try
		{
			System.out.println("Attempt to close output handler");
			isClosing = true;
			_inReader.close();
			System.out.println("ProcessOutputHandler terminated successfully");
		}
		catch (Exception ex)
		{
			System.err.println("ProcessOutputHandler terminated with errors");
		}
	}
}
